package jdos.cpu.core_normal;

import jdos.cpu.CPU;
import jdos.cpu.CPU_Regs;
import jdos.cpu.Core;
import jdos.cpu.Core_full;
import jdos.cpu.Flags;
import jdos.cpu.Instructions;
import jdos.cpu.Paging;
import jdos.cpu.StringOp;
import jdos.cpu.CPU_Regs.Reg;
import jdos.cpu.core_dynamic.Helper;
import jdos.cpu.core_dynamic.Mod;
import jdos.cpu.core_normal.Prefix_helpers.OP;
import jdos.fpu.FPU;
import jdos.hardware.IO;
import jdos.hardware.Memory;
import jdos.hardware.Pic;
import jdos.misc.Log;
import jdos.misc.setup.Config;
import jdos.types.LogSeverities;
import jdos.types.LogTypes;

public class Code extends StringOp {

    static public OP[] ops = new OP[0x100];
    
	static class Targets {
		Target g;
		int ea;
		int bias;
		Target e;
		int which;
	}

	static interface Target {
		void write(int val);

		int read();

		public String toString();
	}

	static class RegTarget implements Target {
		Reg r;
		boolean w;

		public RegTarget(Reg r, boolean w) {
			this.r = r;
			this.w = w;
		}

		int val;
		int oldval;

		public void write(int val) {
			if (w) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					oldval = r.dword;
					r.dword = val;
				} else {
					oldval = r.word();
					r.word(val);
				}
			} else {
				oldval = r.get8();
				r.set8(val);
			}
			this.val = val;
		}

		public int read() {
			if (w) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					val = r.dword;
				} else {
					val = r.word();
				}
			} else {
				val = r.get8();
			}
			return val;
		}

		public String toString() {
			if (w) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					return r.getFullName32() + " " + Integer.toString(oldval, 16) + " " + Integer.toString(val, 16);
				} else {
					return r.getName16() + " " + Integer.toString(oldval, 16) + " " + Integer.toString(val, 16);
				}
			} else {
				return r.getName() + " " + Integer.toString(oldval, 16) + " " + Integer.toString(val, 16);
			}
		}
	}

	static class MemTarget implements Target {
		int eaa;
		boolean w;
		Targets ts;

		public MemTarget(int eaa, boolean w, Targets ts) {
			this.eaa = eaa;
			this.w = w;
			this.ts = ts;
		}

		public void write(int val) {
			if (w) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					Memory.mem_writed(eaa + ts.bias, val);
				} else {
					Memory.mem_writew(eaa + ts.bias, val);
				}
			} else {
				Memory.mem_writeb(eaa + ts.bias, val);
			}
		}

		public int read() {
			if (w) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					return Memory.mem_readd(eaa + ts.bias);
				} else {
					return Memory.mem_readw(eaa + ts.bias);
				}
			} else {
				return Memory.mem_readb(eaa + ts.bias);
			}
		}
	}

	static Targets getTargets(boolean w) {
		/* Bit8u */final int rm = Fetchb();
		Targets ret = new Targets();
		ret.bias = 0;
		ret.g = new RegTarget(w ? Mod.gw(rm) : Mod.gb(rm), w);
		if (rm >= 0xc0) {
			ret.e = new RegTarget(w ? Mod.ew(rm) : Mod.eb(rm), w);
		} else {
			ret.ea = getEaa(rm);
			ret.e = new MemTarget(ret.ea, w, ret);
		}
		ret.which = (rm >> 3) & 7;
		return ret;
	}

	static class OPEbGb extends OP {
		Opnn op;

		public OPEbGb(Opnn op) {
			this.op = op;
		}

		final public int call() {
			Targets t = getTargets(false);
			int val = op.call8(t.g.read(), t.e.read());
			if (op.writeBack()) t.e.write(val);
			return HANDLED;
		}
	};

	static class OPGbEb extends OP {
		Opnn op;

		public OPGbEb(Opnn op) {
			this.op = op;
		}

		final public int call() {
			Targets t = getTargets(false);
			int val = op.call8(t.e.read(), t.g.read());
			if (op.writeBack()) t.g.write(val);
			return HANDLED;
		}
	};

	static class OPEwGw extends OP {
		Opnn op;

		public OPEwGw(Opnn op) {
			this.op = op;
		}

		final public int call() {
			Targets t = getTargets(true);
			int val;
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = op.call32(t.g.read(), t.e.read());
			} else {
				val = op.call16(t.g.read(), t.e.read());
			}
			if (op.writeBack()) t.e.write(val);

			return HANDLED;
		}
	};

	static class OPGwEw extends OP {
		Opnn op;

		public OPGwEw(Opnn op) {
			this.op = op;
		}

		Targets t;

		final public int call() {
			t = getTargets(true);
			int val;
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = op.call32(t.e.read(), t.g.read());
			} else {
				val = op.call16(t.e.read(), t.g.read());
			}
			if (op.writeBack()) t.g.write(val);
			return HANDLED;
		}

		public String toString() {
			return op.toString() + " " + t.g.toString() + " " + t.e.toString();
		}
	};

	static class XCHGOPEbGb extends OP {

		final public int call() {
			Targets t = getTargets(false);
			int val = t.e.read();
			t.e.write(t.g.read());
			t.g.write(val);
			return HANDLED;
		}
	};

	static class XCHGOPEwGw extends OP {
		final public int call() {
			Targets t = getTargets(true);
			int val = t.e.read();
			t.e.write(t.g.read());
			t.g.write(val);
			return HANDLED;
		}
	};

	static class POPEwGw extends OP {
		public POPEwGw() {
		}

		final public int call() {
			int val;
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = CPU.CPU_Pop32();
			} else {
				val = CPU.CPU_Pop16();
			}
			Targets t = getTargets(true);
			t.e.write(val);
			return HANDLED;
		}
	};

	static class OPALIb extends OP {
		Opnn op;

		public OPALIb(Opnn op) {
			this.op = op;
		}

		final public int call() {
			int val = op.call8(Fetchb(), reg_eax.low());
			if (op.writeBack()) reg_eax.low(val);
			return HANDLED;
		}
	};

	static class OPAXIw extends OP {
		Opnn op;

		public OPAXIw(Opnn op) {
			this.op = op;
		}

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				int val = op.call32(Fetchd(), reg_eax.dword);
				if (op.writeBack()) reg_eax.dword = val;
			} else {
				int val = op.call16(Fetchw(), reg_eax.word());
				if (op.writeBack()) reg_eax.word(val);
			}
			return HANDLED;
		}
	};

	static class IncReg extends OP {
		Reg r;

		public IncReg(Reg r) {
			this.r = r;
		}

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				LoadCF();
				var1 = r.dword;
				res = r.dword + 1;
				type = t_INCd;
				r.dword = res;
			} else {
				LoadCF();
				lf_var1w(r.word());
				lf_resw(lf_var1w() + 1);
				r.word(lf_resw());
				type = t_INCw;
			}
			return HANDLED;
		}
	};

	static class DecReg extends OP {
		Reg r;

		public DecReg(Reg r) {
			this.r = r;
		}

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				LoadCF();
				var1 = r.dword;
				res = r.dword - 1;
				type = t_DECd;
				r.dword = res;
			} else {
				LoadCF();
				lf_var1w(r.word());
				lf_resw(lf_var1w() - 1);
				r.word(lf_resw());
				type = t_DECw;
			}
			return HANDLED;
		}
	};

	static class BSWAP extends OP {
		Reg r;

		public BSWAP(Reg r) {
			this.r = r;
		}

		final public int call() {
			if (CPU.CPU_ArchitectureType < CPU.CPU_ARCHTYPE_486OLD) return ILLEGAL_OPCODE;
			if ((prefixes & PREFIX_ADDR) != 0) {
				r.dword = BSWAPD(r.dword);
			} else {
				r.word(Instructions.BSWAPW(r.word()));
			}
			return HANDLED;
		}
	};

	static class Push extends OP {
		Reg r;

		public Push(Reg r) {
			this.r = r;
		}

		int val;

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = r.dword;
				CPU.CPU_Push32(r.dword);
			} else {
				val = r.word();
				CPU.CPU_Push16(r.word());
			}
			return HANDLED;
		}

		public String toString() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				return "PUSH " + r.getFullName32() + " " + Integer.toString(val, 16);
			} else {
				return "PUSH " + r.getName16() + " " + Integer.toString(val, 16);
			}
		}
	};

	static class Pop extends OP {
		Reg r;

		public Pop(Reg r) {
			this.r = r;
		}

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				r.dword = CPU.CPU_Pop32();
			} else {
				r.word(CPU.CPU_Pop16());
			}
			return HANDLED;
		}
	};

	static class PushS extends OP {
		int i;

		public PushS(int i) {
			this.i = i;
		}

		final public int call() {
			int val = CPU.CPU_getSegGeneral_index(i);
			if ((prefixes & Core.PREFIX_DW) != 0) {
				CPU.CPU_Push32(val);
			} else {
				CPU.CPU_Push16(val);
			}
			return HANDLED;
		}
	};

	static class PopS extends OP {
		int i;

		public PopS(int i) {
			this.i = i;
		}

		int val;

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = CPU.CPU_Pop32();
			} else {
				val = CPU.CPU_Pop16();
			}
			if (CPU.CPU_SetSegGeneral_indexNew(i, val)) {
				//System.out.println("f43t54yh6");				System.exit(0);
				return RUNEXCEPTION();
			}
			return HANDLED;
		}

		public String toString() {
			return "PopS " + CPU.getSEG(i) + " " + Integer.toString(val, 16);
		}
	};

	static class XCHGAXW extends OP {
		Reg r;

		public XCHGAXW(Reg r) {
			this.r = r;
		}

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				/* Bit16u */int temp = reg_eax.dword;
				reg_eax.dword = r.dword;
				r.dword = temp;
			} else {
				/* Bit16u */int temp = reg_eax.word();
				reg_eax.word(r.word());
				r.word(temp);
			}
			return HANDLED;
		}
	};

	static class MOVRegBIb extends OP {
		Reg r;

		public MOVRegBIb(Reg r) {
			this.r = r;
		}

		final public int call() {
			r.set8(Fetchb());
			return HANDLED;
		}
	};

	static class MOVRegBIw extends OP {
		Reg r;

		public MOVRegBIw(Reg r) {
			this.r = r;
		}

		int val;
		int oldval;

		final public int call() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				oldval = r.dword;
				r.dword = Fetchd();
				val = r.dword;
			} else {
				oldval = r.word();
				r.word(Fetchw());
				val = r.word();
			}
			return HANDLED;
		}

		public String toString() {
			if ((prefixes & Core.PREFIX_DW) != 0) {
				return "MOV " + r.getFullName32() + " " + Integer.toString(oldval, 16) + " " + Integer.toString(val, 16);
			} else {
				return "MOV " + r.getName16() + " " + Integer.toString(oldval, 16) + " " + Integer.toString(val, 16);
			}
		}
	};

	static class SHIFTb extends OP {
		int blahCase;

		public SHIFTb(int blahCase) {// 0:fetch,1:1,2:cl
			this.blahCase = blahCase;
		}

		final public int call() {
			Targets t = getTargets(false);
			Opnn op = getSHIFTOp(t.which);
			/* Bit8u */int shift = 0;
			switch (blahCase) {
			case 0:
				int blah = Fetchb();
				shift = blah & 0x1f;
				break;
			case 1:
				shift = 1;
				break;
			case 2:
				shift = reg_ecx.low();
				break;
			}
			int val = op.call8(shift, t.e.read());
			if (op.writeBack()) t.e.write(val);
			return HANDLED;
		}
	};

	static class SHIFTw extends OP {
		int blahCase;

		public SHIFTw(int blahCase) {// 0:fetch,1:1,2:cl
			this.blahCase = blahCase;
		}

		final public int call() {
			Targets t = getTargets(true);
			Opnn op = getSHIFTOp(t.which);
			/* Bit8u */int shift = 0;
			switch (blahCase) {
			case 0:
				int blah = Fetchb();
				shift = blah & 0x1f;
				break;
			case 1:
				shift = 1;
				break;
			case 2:
				shift = reg_ecx.low();
				break;
			}
			int val;
			if ((prefixes & Core.PREFIX_DW) != 0) {
				val = op.call32(shift, t.e.read());
			} else {
				val = op.call16(shift, t.e.read());
			}
			if (op.writeBack()) t.e.write(val);
			return HANDLED;
		}
	};

	static class JMP extends OP {
		int index;
		boolean far;

		public JMP(int index, boolean far) {
			this.index = index;
			this.far = far;
		}

		final public int call() {
			if (far) {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					JumpCond32_d(TFLG(index));
				} else {
					JumpCond16_w(TFLG(index));
				}
			} else {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					JumpCond32_b(TFLG(index));
				} else {
					JumpCond16_b(TFLG(index));
				}
			}
			return CONTINUE;
		}
	};

	static class SETcc extends OP {
		int index;

		public SETcc(int index) {
			this.index = index;
		}

		final public int call() {
			Targets t = getTargets(false);
			boolean cc = TFLG(index);
			t.e.write((cc) ? 1 : 0);
			return HANDLED;
		}
	};

	static class LOOP extends OP {
		boolean loop;
		boolean z;
		boolean nz;

		public LOOP(boolean loop, boolean z, boolean nz) {
			this.loop = loop;
			this.z = z;
			this.nz = nz;
		}

		final public int call() {

			boolean flg;
			if (loop) {
				if ((prefixes & PREFIX_ADDR) != 0) {
					reg_ecx.dword--;
					flg = reg_ecx.dword != 0;
				} else {
					reg_ecx.word(reg_ecx.word() - 1);
					flg = reg_ecx.word() != 0;
				}
			} else {
				if ((prefixes & PREFIX_ADDR) != 0) {
					flg = reg_ecx.dword == 0;
				} else {
					flg = reg_ecx.word() == 0;
				}
			}

			if (nz) {
				flg &= !Flags.get_ZF();
			}
			if (z) {
				flg &= Flags.get_ZF();
			}

			if ((prefixes & Core.PREFIX_DW) != 0) {
				JumpCond32_b(flg);
			} else {
				JumpCond16_b(flg);
			}

			return CONTINUE;
		}
	};

	static class IOOp extends OP {
		boolean input;
		boolean w;
		boolean dx;

		public IOOp(boolean input, boolean w, boolean dx) {
			this.input = input;
			this.w = w;
			this.dx = dx;
		}

		final public int call() {
			/* Bitu */int port;
			if (dx) {
				port = reg_edx.word();
			} else {
				port = Fetchb();
			}

			if (!w) {
				if (CPU.CPU_IO_Exception(port, 1)) return RUNEXCEPTION();
			} else {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					if (CPU.CPU_IO_Exception(port, 4)) return RUNEXCEPTION();
				} else {
					if (CPU.CPU_IO_Exception(port, 2)) return RUNEXCEPTION();
				}
			}

			if (input) {
				if (!w) {
					reg_eax.low(IO.IO_ReadB(port));
				} else {
					if ((prefixes & Core.PREFIX_DW) != 0) {
						System.out.println("fd55676safdsa");
						System.exit(0);
						reg_eax.dword = IO.IO_ReadD(port);
					} else {
						reg_eax.word(IO.IO_ReadW(port));
					}
				}
			} else {
				if (!w) {
					IO.IO_WriteB(port, reg_eax.low());
				} else {
					if ((prefixes & Core.PREFIX_DW) != 0) {
						System.out.println("fd55676safdsa");
						System.exit(0);
						IO.IO_WriteD(port, reg_eax.dword);
					} else {
						IO.IO_WriteW(port, reg_eax.word());
					}
				}
			}
			return HANDLED;

		}
	};

	static class LxS extends OP {
		int index;

		public LxS(int index) {
			this.index = index;
		}

		final public int call() {
			/* Bit8u */int rm = Fetchb();
			if (rm >= 0xc0) return ILLEGAL_OPCODE;
			Reg rw = Mod.gw(rm);
			/* PhysPt */int eaa = getEaa(rm);
			if ((prefixes & Core.PREFIX_DW) != 0) {
				int val = Memory.mem_readd(eaa); // make sure all reads are done before writing something in case of a PF
				if (CPU.CPU_SetSegGeneral_indexNew(index, Memory.mem_readw(eaa + 4))) return RUNEXCEPTION();
				rw.dword = val;
			} else {
				int val = Memory.mem_readw(eaa); // make sure all reads are done before writing something in case of a PF
				if (CPU.CPU_SetSegGeneral_indexNew(index, Memory.mem_readw(eaa + 2))) return RUNEXCEPTION();
				rw.word(val);
			}
			return HANDLED;
		}
	};

	static class BTx extends OP {
		int type;

		public BTx(int type) {
			this.type = type;
		}

		//		BT (Bit Test) CF flag ~ Selected Bit no effect
		//		BTS (Bit Test .and Set) CF flag ~ Selected Bit Selected Bit ~ 1
		//		BTR (Bit Test and Reset) CF flag ~ Selected Bit Selected Bit ~ 0
		//		BTC (Bit Test and Complement) CF flag ~ Selected Bit Selected Bit ~ - (Selected Bit)
		final public int call() {
			Flags.FillFlags();
			Targets t = getTargets(true);
			if ((prefixes & Core.PREFIX_DW) != 0) {
				/*Bit32u*/int mask = 1 << (t.g.read() & 31);
				t.bias = (t.g.read() >> 5) * 4;
				// intentional signed shift
				/*Bit32u*/int old = t.e.read();
				SETFLAGBIT(CF, (old & mask) != 0);
				switch (type) {
				case 0:
					break;
				case 1:
					t.e.write(old | mask);
					break;
				case 2:
					t.e.write(old & ~mask);
					break;
				case 3:
					t.e.write(old ^ mask);
					break;
				}
			} else {
				/*Bit16u*/int mask = 1 << (t.g.read() & 15);
				t.bias = (((/*Bit16s*/short) t.g.read()) >> 4) * 2;
				/*Bit16u*/int old = t.e.read();
				SETFLAGBIT(CF, (old & mask) != 0);
				switch (type) {
				case 0:
					break;
				case 1:
					t.e.write(old | mask);
					break;
				case 2:
					t.e.write(old & ~mask);
					break;
				case 3:
					t.e.write(old ^ mask);
					break;
				}

			}
			return HANDLED;
		}
	};

    public static OP not_handled = new OP() {
        public int call() {
            return NOT_HANDLED;
        }
    };

	static {

        for (int i=0;i<ops.length;i++)
            ops[i] = not_handled;


		/* ADD Eb,Gb */ ops[0x00] = new OPEbGb(getOp(0));
		/* ADD Ew,Gw */ ops[0x01] = new OPEwGw(getOp(0));
		/* ADD Gb,Eb */ ops[0x02] = new OPGbEb(getOp(0));
		/* ADD Gw,Ew */ ops[0x03] = new OPGwEw(getOp(0));
		/* ADD AL,Ib */ ops[0x04] = new OPALIb(getOp(0));
		/* ADD AX,Iw */ ops[0x05] = new OPAXIw(getOp(0));
		/* PUSH ES */ ops[0x06] = new PushS(0);
		/* POP ES */ ops[0x07] = new PopS(0);

		/* OR Eb,Gb */ ops[0x08] = new OPEbGb(getOp(1));
		/* OR Ew,Gw */ ops[0x09] = new OPEwGw(getOp(1));
		/* OR Gb,Eb */ ops[0x0a] = new OPGbEb(getOp(1));
		/* OR Gw,Ew */ ops[0x0b] = new OPGwEw(getOp(1));
		/* OR AL,Ib */ ops[0x0c] = new OPALIb(getOp(1));
		/* OR AX,Iw */ ops[0x0d] = new OPAXIw(getOp(1));
		/* PUSH CS */ ops[0x0e] = new PushS(1);

		/* ADC Eb,Gb */ ops[0x10] = new OPEbGb(getOp(2));
		/* ADC Ew,Gw */ ops[0x11] = new OPEwGw(getOp(2));
		/* ADC Gb,Eb */ ops[0x12] = new OPGbEb(getOp(2));
		/* ADC Gw,Ew */ ops[0x13] = new OPGwEw(getOp(2));
		/* ADC AL,Ib */ ops[0x14] = new OPALIb(getOp(2));
		/* ADC AX,Iw */ ops[0x15] = new OPAXIw(getOp(2));
		/* PUSH SS */ ops[0x16] = new PushS(2);
		/* POP SS */ ops[0x17] = new PopS(2);

		/* SBB Eb,Gb */ ops[0x18] = new OPEbGb(getOp(3));
		/* SBB Ew,Gw */ ops[0x19] = new OPEwGw(getOp(3));
		/* SBB Gb,Eb */ ops[0x1a] = new OPGbEb(getOp(3));
		/* SBB Gw,Ew */ ops[0x1b] = new OPGwEw(getOp(3));
		/* SBB AL,Ib */ ops[0x1c] = new OPALIb(getOp(3));
		/* SBB AX,Iw */ ops[0x1d] = new OPAXIw(getOp(3));
		/* PUSH DS */ ops[0x1e] = new PushS(3);
		/* POP DS */ ops[0x1f] = new PopS(3);

		/* AND Eb,Gb */ ops[0x20] = new OPEbGb(getOp(4));
		/* AND Ew,Gw */ ops[0x21] = new OPEwGw(getOp(4));
		/* AND Gb,Eb */ ops[0x22] = new OPGbEb(getOp(4));
		/* AND Gw,Ew */ ops[0x23] = new OPGwEw(getOp(4));
		/* AND AL,Ib */ ops[0x24] = new OPALIb(getOp(4));
		/* AND AX,Iw */ ops[0x25] = new OPAXIw(getOp(4));
		/* DAA */
		ops[0x27] = new OP() {
			final public int call() {
				Instructions.DAA();
				return HANDLED;
			}
		};

		/* SUB Eb,Gb */ ops[0x28] = new OPEbGb(getOp(5));
		/* SUB Ew,Gw */ ops[0x29] = new OPEwGw(getOp(5));
		/* SUB Gb,Eb */ ops[0x2a] = new OPGbEb(getOp(5));
		/* SUB Gw,Ew */ ops[0x2b] = new OPGwEw(getOp(5));
		/* SUB AL,Ib */ ops[0x2c] = new OPALIb(getOp(5));
		/* SUB AX,Iw */ ops[0x2d] = new OPAXIw(getOp(5));
		/* DAS */
		ops[0x2f] = new OP() {
			final public int call() {
				Instructions.DAS();
				return HANDLED;
			}
		};

		/* XOR Eb,Gb */ ops[0x30] = new OPEbGb(getOp(6));
		/* XOR Ew,Gw */ ops[0x31] = new OPEwGw(getOp(6));
		/* XOR Gb,Eb */ ops[0x32] = new OPGbEb(getOp(6));
		/* XOR Gw,Ew */ ops[0x33] = new OPGwEw(getOp(6));
		/* XOR AL,Ib */ ops[0x34] = new OPALIb(getOp(6));
		/* XOR AX,Iw */ ops[0x35] = new OPAXIw(getOp(6));
		/* AAA */
		ops[0x37] = new OP() {
			final public int call() {
				Instructions.AAA();
				return HANDLED;
			}
		};

		/* CMP Eb,Gb */ ops[0x38] = new OPEbGb(getOp(7));
		/* CMP Ew,Gw */ ops[0x39] = new OPEwGw(getOp(7));
		/* CMP Gb,Eb */ ops[0x3a] = new OPGbEb(getOp(7));
		/* CMP Gw,Ew */ ops[0x3b] = new OPGwEw(getOp(7));
		/* CMP AL,Ib */ ops[0x3c] = new OPALIb(getOp(7));
		/* CMP AX,Iw */ ops[0x3d] = new OPAXIw(getOp(7));
		/* AAS */
		ops[0x3f] = new OP() {
			final public int call() {
				Instructions.AAS();
				return HANDLED;
			}
		};

		/* INC AX */ ops[0x40] = new IncReg(Mod.ew(0));
		/* INC CX */ ops[0x41] = new IncReg(Mod.ew(1));
		/* INC DX */ ops[0x42] = new IncReg(Mod.ew(2));
		/* INC BX */ ops[0x43] = new IncReg(Mod.ew(3));
		/* INC SP */ ops[0x44] = new IncReg(Mod.ew(4));
		/* INC BP */ ops[0x45] = new IncReg(Mod.ew(5));
		/* INC SI */ ops[0x46] = new IncReg(Mod.ew(6));
		/* INC DI */ ops[0x47] = new IncReg(Mod.ew(7));

		/* DEC AX */ ops[0x48] = new DecReg(Mod.ew(0));
		/* DEC CX */ ops[0x49] = new DecReg(Mod.ew(1));
		/* DEC DX */ ops[0x4a] = new DecReg(Mod.ew(2));
		/* DEC BX */ ops[0x4b] = new DecReg(Mod.ew(3));
		/* DEC SP */ ops[0x4c] = new DecReg(Mod.ew(4));
		/* DEC BP */ ops[0x4d] = new DecReg(Mod.ew(5));
		/* DEC SI */ ops[0x4e] = new DecReg(Mod.ew(6));
		/* DEC DI */ ops[0x4f] = new DecReg(Mod.ew(7));

		/* PUSH AX */ ops[0x50] = new Push(Mod.ew(0));
		/* PUSH CX */ ops[0x51] = new Push(Mod.ew(1));
		/* PUSH DX */ ops[0x52] = new Push(Mod.ew(2));
		/* PUSH BX */ ops[0x53] = new Push(Mod.ew(3));
		/* PUSH SP */ ops[0x54] = new Push(Mod.ew(4));
		/* PUSH BP */ ops[0x55] = new Push(Mod.ew(5));
		/* PUSH SI */ ops[0x56] = new Push(Mod.ew(6));
		/* PUSH DI */ ops[0x57] = new Push(Mod.ew(7));

		/* POP AX */ ops[0x58] = new Pop(Mod.ew(0));
		/* POP CX */ ops[0x59] = new Pop(Mod.ew(1));
		/* POP DX */ ops[0x5a] = new Pop(Mod.ew(2));
		/* POP BX */ ops[0x5b] = new Pop(Mod.ew(3));
		/* POP SP */ ops[0x5c] = new Pop(Mod.ew(4));
		/* POP BP */ ops[0x5d] = new Pop(Mod.ew(5));
		/* POP SI */ ops[0x5e] = new Pop(Mod.ew(6));
		/* POP DI */ ops[0x5f] = new Pop(Mod.ew(7));

		/* PUSHA */
		ops[0x60] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bitu */int tmpesp = reg_esp.dword;
					int esp = reg_esp.dword;
					esp = CPU.CPU_Push32(esp, reg_eax.dword);
					esp = CPU.CPU_Push32(esp, reg_ecx.dword);
					esp = CPU.CPU_Push32(esp, reg_edx.dword);
					esp = CPU.CPU_Push32(esp, reg_ebx.dword);
					esp = CPU.CPU_Push32(esp, tmpesp);
					esp = CPU.CPU_Push32(esp, reg_ebp.dword);
					esp = CPU.CPU_Push32(esp, reg_esi.dword);
					esp = CPU.CPU_Push32(esp, reg_edi.dword);
					// Don't store ESP until all the memory writes are done in case of a PF so that
					// this op can be reentrant
					reg_esp.dword = esp;
				} else {
					/* Bit16u */int old_sp = reg_esp.word();
					int esp = reg_esp.dword;
					esp = CPU.CPU_Push16(esp, reg_eax.word());
					esp = CPU.CPU_Push16(esp, reg_ecx.word());
					esp = CPU.CPU_Push16(esp, reg_edx.word());
					esp = CPU.CPU_Push16(esp, reg_ebx.word());
					esp = CPU.CPU_Push16(esp, old_sp);
					esp = CPU.CPU_Push16(esp, reg_ebp.word());
					esp = CPU.CPU_Push16(esp, reg_esi.word());
					esp = CPU.CPU_Push16(esp, reg_edi.word());
					// Don't store ESP until all the memory writes are done in case of a PF so that
					// this op can be reentrant
					reg_esp.word(esp);
				}
				return HANDLED;
			}
		};

		/* POPA */
		ops[0x61] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_edi.dword = CPU.CPU_Pop32();
					reg_esi.dword = CPU.CPU_Pop32();
					reg_ebp.dword = CPU.CPU_Pop32();
					CPU.CPU_Pop32();// Don't save ESP
					reg_ebx.dword = CPU.CPU_Pop32();
					reg_edx.dword = CPU.CPU_Pop32();
					reg_ecx.dword = CPU.CPU_Pop32();
					reg_eax.dword = CPU.CPU_Pop32();
				} else {
					reg_edi.word(CPU.CPU_Pop16());
					reg_esi.word(CPU.CPU_Pop16());
					reg_ebp.word(CPU.CPU_Pop16());
					CPU.CPU_Pop16();// Don't save SP
					reg_ebx.word(CPU.CPU_Pop16());
					reg_edx.word(CPU.CPU_Pop16());
					reg_ecx.word(CPU.CPU_Pop16());
					reg_eax.word(CPU.CPU_Pop16());
				}
				return HANDLED;
			}
		};

		/* BOUND */
		ops[0x62] = new OP() {
			final public int call() {
				/* Bit8u */int rm = Fetchb();
				Reg reg = Mod.gw(rm);
				/* PhysPt */int eaa = getEaa(rm);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bit32s */int bound_min, bound_max;
					bound_min = Memory.mem_readd(eaa);
					bound_max = Memory.mem_readd(eaa + 4);
					int rmrd = reg.dword;
					if (rmrd < bound_min || rmrd > bound_max) {
						return EXCEPTION(5);
					}
				} else {
					short bound_min = (short) Memory.mem_readw(eaa);
					short bound_max = (short) Memory.mem_readw(eaa + 2);
					if ((((short) reg.word()) < bound_min) || (((short) reg.word()) > bound_max)) {
						return EXCEPTION(5);
					}
				}
				return HANDLED;
			}
		};

		/* ARPL Ew,Rw (Adjust Requested Privilege Level)*/
		ops[0x63] = new OP() {
			final public int call() {
				boolean a = CPU.cpu.pmode;
				boolean b = (CPU_Regs.flags & CPU_Regs.VM) != 0;
				if (b || !a) return ILLEGAL_OPCODE;
				System.out.print("fe3jw8934fu843f");
				System.exit(0);
				/* Bit8u */int rm = Fetchb();
				Reg rw = Mod.gw(rm);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					if (rm >= 0xc0) {
						Reg earw = Mod.ew(rm);
						int value = CPU.CPU_ARPL(earw.word(), rw.word());
						earw.word(value);
					} else {
						/* PhysPt */int eaa = getEaa(rm);
						int value = Memory.mem_readw(eaa);
						value = CPU.CPU_ARPL(value, rw.word());
						Memory.mem_writew(eaa, value);
					}
				} else {
					if (rm >= 0xc0) {
						Reg earw = Mod.ew(rm);
						rw.dword = CPU.CPU_ARPL(earw.dword, rw.word());
					} else {
						/* PhysPt */int eaa = getEaa(rm);
						int value = Memory.mem_readw(eaa);
						value = CPU.CPU_ARPL(value, rw.word());
						Memory.mem_writed(eaa, value);
					}
				}
				return HANDLED;
			}
		};

		/* PUSH Iw */
		ops[0x68] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					CPU.CPU_Push32(Fetchd());
				} else {
					CPU.CPU_Push16(Fetchw());
				}
				return HANDLED;
			}
		};

		/* IMUL Gw,Ew,Iw *//* IMUL Gd,Ed,Id */
		ops[0x69] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					int op3 = Fetchds();
					t.g.write(DIMULD(t.e.read(), op3));
				} else {
					int op3 = Fetchws();
					t.g.write(DIMULW(t.e.read(), op3));
				}
				return HANDLED;
			}
		};

		/* PUSH Ib */
		ops[0x6a] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					CPU.CPU_Push32(Fetchbs());
				} else {
					CPU.CPU_Push16(Fetchbs());
				}
				return HANDLED;
			}
		};

		/* IMUL Gw,Ew,Ib */
		ops[0x6b] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					int op3 = Fetchbs();
					t.g.write(DIMULD(t.e.read(), op3));
				} else {
					int op3 = Fetchbs();
					t.g.write(DIMULW(t.e.read(), op3));
				}
				return HANDLED;
			}
		};

		/* INSB */
		ops[0x6c] = new OP() {
			final public int call() {
				if (CPU.CPU_IO_Exception(reg_edx.word(), 1)) return RUNEXCEPTION();
				DoString(R_INSB);
				return HANDLED;
			}
		};

		/* INSW */
		ops[0x6d] = new OP() {
			final public int call() {
				if (CPU.CPU_IO_Exception(reg_edx.word(), ((prefixes & Core.PREFIX_DW) != 0) ? 4 : 2)) return RUNEXCEPTION();
				DoString(((prefixes & Core.PREFIX_DW) != 0) ? R_INSD : R_INSW);
				return HANDLED;
			}
		};

		/* OUTSB */
		ops[0x6e] = new OP() {
			final public int call() {
				if (CPU.CPU_IO_Exception(reg_edx.word(), 1)) return RUNEXCEPTION();
				DoString(R_OUTSB);
				return HANDLED;
			}
		};

		/* OUTSW */
		ops[0x6f] = new OP() {
			final public int call() {
				if (CPU.CPU_IO_Exception(reg_edx.word(), ((prefixes & Core.PREFIX_DW) != 0) ? 4 : 2)) return RUNEXCEPTION();
				DoString(((prefixes & Core.PREFIX_DW) != 0) ? R_OUTSD : R_OUTSW);
				return HANDLED;
			}
		};

		/* JO  */ ops[0x70] = new JMP(0x0, false);
		/* JNO  */ ops[0x71] = new JMP(0x1, false);
		/* JB   */ ops[0x72] = new JMP(0x2, false);
		/* JNB  */ ops[0x73] = new JMP(0x3, false);
		/* JZ   */ ops[0x74] = new JMP(0x4, false);
		/* JNZ  */ ops[0x75] = new JMP(0x5, false);
		/* JBE  */ ops[0x76] = new JMP(0x6, false);
		/* JNBE */ ops[0x77] = new JMP(0x7, false);
		/* JS   */ ops[0x78] = new JMP(0x8, false);
		/* JNS  */ ops[0x79] = new JMP(0x9, false);
		/* JP   */ ops[0x7a] = new JMP(0xa, false);
		/* JNP  */ ops[0x7b] = new JMP(0xb, false);
		/* JL   */ ops[0x7c] = new JMP(0xc, false);
		/* JNL  */ ops[0x7d] = new JMP(0xd, false);
		/* JLE  */ ops[0x7e] = new JMP(0xe, false);
		/* JNLE */ ops[0x7f] = new JMP(0xf, false);

		/* Grpl Eb,Ib */
		ops[0x80] = new OP() {
			final public int call() {
				Targets t = getTargets(false);
				Opnn op = getOp(t.which);
				/* Bit8u */int ib = Fetchb();
				int val = op.call8(ib, t.e.read());
				if (op.writeBack()) t.e.write(val);
				return HANDLED;
			}
		};

		/* Grpl Ew,Iw */
		ops[0x81] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				Opnn op = getOp(t.which);
				int val;
				if ((prefixes & Core.PREFIX_DW) != 0) {
					int iw = Fetchd();
					val = op.call32(iw, t.e.read());
				} else {
					int iw = Fetchw();
					val = op.call16(iw, t.e.read());
				}
				if (op.writeBack()) t.e.write(val);
				return HANDLED;

			}
		};

		/* Grpl Eb,Ib Mirror instruction*/
		ops[0x82] = ops[0x80];

		/* Grpl Ew,Ix */
		ops[0x83] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				Opnn op = getOp(t.which);
				int b = Fetchbs();
				int val;
				if ((prefixes & Core.PREFIX_DW) != 0) {
					int iw = b;
					val = op.call32(iw, t.e.read());
				} else {
					/* Bit16u */int iw = (((short) b) & 0xFFFF);
					val = op.call16(iw, t.e.read());
				}
				if (op.writeBack()) t.e.write(val);
				return HANDLED;
			}
		};

		/* TEST Eb,Gb */ ops[0x84] = new OPEbGb(new TEST());
		/* TEST Ew,Gw */ ops[0x85] = new OPEwGw(new TEST());
		/* XCHG Eb,Gb */ ops[0x86] = new XCHGOPEbGb();
		/* XCHG Ew,Gw */ ops[0x87] = new XCHGOPEwGw();
		/* MOV Eb,Gb */ ops[0x88] = new OPEbGb(new MOV());
		/* MOV Ew,Gw */ ops[0x89] = new OPEwGw(new MOV());
		/* MOV Gb,Eb */ ops[0x8a] = new OPGbEb(new MOV());
		/* MOV Gw,Ew */ ops[0x8b] = new OPGwEw(new MOV());

		/* Mov Ew,Sw */
		ops[0x8c] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				final Reg s = Helper.getSreg(t.which);
				t.e.write(s.word());
				return HANDLED;
			}
		};

		/* LEA Gw */
		ops[0x8d] = new OP() {
			final public int call() {
				base_ds = base_ss = 0;
				Targets t = getTargets(true);
				t.g.write(t.ea);
				base_ds = CPU_Regs.reg_dsPhys;
				base_ss = CPU_Regs.reg_ssPhys;
				return HANDLED;
			}
		};

		/* MOV Sw,Ew */
		ops[0x8e] = new OP() {
			int which;
			Targets t;

			final public int call() {
				t = getTargets(true);
				/* Bit16u */int val = t.e.read();
				which = t.which;
				if (which == 2) {
					CPU.CPU_Cycles++; //Always do another instruction
				}
				if (CPU.CPU_SetSegGeneral_indexNew(which, val & 0xFFFF)) return RUNEXCEPTION();
				return HANDLED;
			}

			public String toString() {
				return "MOV" + " " + CPU.getSEG(which) + " " + t.e.toString();
			}
		};

		/* POP Ew */
		ops[0x8f] = new POPEwGw();

		/* NOP XCHG AX,AX*/ ops[0x90] = new XCHGAXW(Mod.ew(0));
		/* XCHG CX,AX */ ops[0x91] = new XCHGAXW(Mod.ew(1));
		/* XCHG DX,AX */ ops[0x92] = new XCHGAXW(Mod.ew(2));
		/* XCHG BX,AX */ ops[0x93] = new XCHGAXW(Mod.ew(3));
		/* XCHG SP,AX */ ops[0x94] = new XCHGAXW(Mod.ew(4));
		/* XCHG BP,AX */ ops[0x95] = new XCHGAXW(Mod.ew(5));
		/* XCHG SI,AX */ ops[0x96] = new XCHGAXW(Mod.ew(6));
		/* XCHG DI,AX */ ops[0x97] = new XCHGAXW(Mod.ew(7));

		/* CBW */
		ops[0x98] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_eax.dword = (short) reg_eax.word();
				} else {
					reg_eax.word((byte) reg_eax.low());
				}
				return HANDLED;
			}
		};

		/* CWD */
		ops[0x99] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					if ((reg_eax.dword & 0x80000000) != 0) reg_edx.dword = 0xffffffff;
					else reg_edx.dword = 0;
				} else {
					if ((reg_eax.word() & 0x8000) != 0) reg_edx.word(0xffff);
					else reg_edx.word(0);
				}
				return HANDLED;
			}
		};

		/* CALL Ap */
		ops[0x9a] = new OP() {
			final public int call() {
				FillFlags();
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bit32u */int newip = Fetchd();
					/* Bit16u */int newcs = Fetchw();
					CPU.CPU_CALL(true, newcs, newip, GETIP());
				} else {
					/* Bit16u */int newip = Fetchw();
					/* Bit16u */int newcs = Fetchw();
					CPU.CPU_CALL(false, newcs, newip, GETIP());
				}
				if (CPU_TRAP_CHECK) {
					if (GETFLAG(TF) != 0) {
						CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
						return CBRET_NONE;
					}
				}
				return CONTINUE;
			}
		};

		/* WAIT */
		ops[0x9b] = new OP() {
			final public int call() {
				/* No waiting here */
				return HANDLED;
			}
		};

		/* PUSHF */
		ops[0x9c] = new OP() {
			final public int call() {
				if (CPU.CPU_PUSHF((prefixes & Core.PREFIX_DW) != 0)) return RUNEXCEPTION();
				return HANDLED;
			}
		};

		/* POPF */
		ops[0x9d] = new OP() {
			final public int call() {
				if (CPU.CPU_POPF((prefixes & Core.PREFIX_DW) != 0)) return RUNEXCEPTION();
				if (CPU_TRAP_CHECK) {
					if (GETFLAG(TF) != 0) {
						CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
						return DECODE_END;
					}
				}
				if (CPU_PIC_CHECK) if (GETFLAG(IF) != 0 && Pic.PIC_IRQCheck != 0) return DECODE_END;
				return HANDLED;
			}
		};

		/* SAHF */
		ops[0x9e] = new OP() {
			final public int call() {
				Flags.SETFLAGSb(reg_eax.high());
				return HANDLED;
			}
		};

		/* LAHF */
		ops[0x9f] = new OP() {
			final public int call() {
				Flags.FillFlags();
				reg_eax.high(CPU_Regs.flags & 0xff);
				return HANDLED;
			}
		};

		/* MOV AL,Ob */
		ops[0xa0] = new OP() {
			final public int call() {
				reg_eax.low(Memory.mem_readb(GetEADirect()));
				return HANDLED;
			}
		};

		/* MOV AX,Ow */
		ops[0xa1] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_eax.dword = Memory.mem_readd(GetEADirect());
				} else {
					reg_eax.word(Memory.mem_readw(GetEADirect()));
				}
				return HANDLED;
			}
		};

		/* MOV Ob,AL */
		ops[0xa2] = new OP() {
			final public int call() {
				Memory.mem_writeb(GetEADirect(), reg_eax.low());
				return HANDLED;
			}
		};

		/* MOV Ow,AX */
		ops[0xa3] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					Memory.mem_writed(GetEADirect(), reg_eax.dword);
				} else {
					Memory.mem_writew(GetEADirect(), reg_eax.word());
				}
				return HANDLED;
			}
		};

		/* MOVSB */
		ops[0xa4] = new OP() {
			final public int call() {
				DoString(R_MOVSB);
				return HANDLED;
			}
		};

		/* MOVSW */
		ops[0xa5] = new OP() {
			final public int call() {
				DoString((prefixes & Core.PREFIX_DW) != 0 ? R_MOVSD : R_MOVSW);
				return HANDLED;
			}

			public String toString() {
				return "MOVSW";
			}
		};

		/* CMPSB */
		ops[0xa6] = new OP() {
			final public int call() {
				DoString(R_CMPSB);
				return HANDLED;
			}
		};

		/* CMPSW */
		ops[0xa7] = new OP() {
			final public int call() {
				DoString((prefixes & Core.PREFIX_DW) != 0 ? R_CMPSD : R_CMPSW);
				return HANDLED;
			}
		};

		/* TEST AL,Ib */ ops[0xa8] = new OPALIb(new TEST());
		/* TEST AX,Iw */ ops[0xa9] = new OPAXIw(new TEST());

		/* STOSB */
		ops[0xaa] = new OP() {
			final public int call() {
				DoString(R_STOSB);
				return HANDLED;
			}
		};

		/* STOSW */
		ops[0xab] = new OP() {
			final public int call() {
				DoString((prefixes & Core.PREFIX_DW) != 0 ? R_STOSD : R_STOSW);
				return HANDLED;
			}
		};

		/* LODSB */
		ops[0xac] = new OP() {
			final public int call() {
				DoString(R_LODSB);
				return HANDLED;
			}
		};

		/* LODSW */
		ops[0xad] = new OP() {
			final public int call() {
				DoString((prefixes & Core.PREFIX_DW) != 0 ? R_LODSD : R_LODSW);
				return HANDLED;
			}
		};

		/* SCASB */
		ops[0xae] = new OP() {
			final public int call() {
				DoString(R_SCASB);
				return HANDLED;
			}
		};

		/* SCASW */
		ops[0xaf] = new OP() {
			final public int call() {
				DoString((prefixes & Core.PREFIX_DW) != 0 ? R_SCASD : R_SCASW);
				return HANDLED;
			}
		};

		/* MOV AL,Ib */ ops[0xb0] = new MOVRegBIb(Mod.eb(0));
		/* MOV CL,Ib */ ops[0xb1] = new MOVRegBIb(Mod.eb(1));
		/* MOV DL,Ib */ ops[0xb2] = new MOVRegBIb(Mod.eb(2));
		/* MOV BL,Ib */ ops[0xb3] = new MOVRegBIb(Mod.eb(3));
		/* MOV AH,Ib */ ops[0xb4] = new MOVRegBIb(Mod.eb(4));
		/* MOV CH,Ib */ ops[0xb5] = new MOVRegBIb(Mod.eb(5));
		/* MOV DH,Ib */ ops[0xb6] = new MOVRegBIb(Mod.eb(6));
		/* MOV BH,Ib */ ops[0xb7] = new MOVRegBIb(Mod.eb(7));

		/* MOV AX,Iw */ ops[0xb8] = new MOVRegBIw(Mod.ew(0));
		/* MOV CX,Iw */ ops[0xb9] = new MOVRegBIw(Mod.ew(1));
		/* MOV DX,Iw */ ops[0xba] = new MOVRegBIw(Mod.ew(2));
		/* MOV BX,Iw */ ops[0xbb] = new MOVRegBIw(Mod.ew(3));
		/* MOV SP,Iw */ ops[0xbc] = new MOVRegBIw(Mod.ew(4));
		/* MOV BP.Iw */ ops[0xbd] = new MOVRegBIw(Mod.ew(5));
		/* MOV SI,Iw */ ops[0xbe] = new MOVRegBIw(Mod.ew(6));
		/* MOV DI,Iw */ ops[0xbf] = new MOVRegBIw(Mod.ew(7));

		/* GRP2 Eb,Ib */ ops[0xc0] = new SHIFTb(0);
		/* GRP2 Ew,Ib */ ops[0xc1] = new SHIFTw(0);

		/* RETN Iw */
		ops[0xc2] = new OP() {
			final public int call() {
				int offset = Fetchw();
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_eip = CPU.CPU_Pop32();
				} else {
					reg_eip = CPU.CPU_Pop16();
				}
				reg_esp.dword += offset;
				return CONTINUE;
			}
		};

		/* RETN */
		ops[0xc3] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_eip = CPU.CPU_Pop32();
				} else {
					reg_eip = CPU.CPU_Pop16();
				}
				return CONTINUE;
			}
		};

		/* LES */
		ops[0xc4] = new LxS(0);

		/* LDS */
		ops[0xc5] = new LxS(3);

		/* MOV Eb,Ib */
		ops[0xc6] = new OP() {
			final public int call() {
				Targets t = getTargets(false);
				/* Bit8u */int ib = Fetchb();
				t.e.write(ib);
				return HANDLED;
			}
		};

		/* MOV Ew,Iw */
		ops[0xc7] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				int iw;
				if ((prefixes & Core.PREFIX_DW) != 0) {
					iw = Fetchd();
				} else {
					iw = Fetchw();
				}
				t.e.write(iw);
				return HANDLED;
			}
		};

		/* ENTER Iw,Ib */
		ops[0xc8] = new OP() {
			final public int call() {
				/* Bitu */int bytes = Fetchw();
				/* Bitu */int level = Fetchb();
				CPU.CPU_ENTER((prefixes & Core.PREFIX_DW) != 0, bytes, level);
				return HANDLED;
			}
		};

		/* LEAVE */
		ops[0xc9] = new OP() {
			final public int call() {
				reg_esp.dword &= CPU.cpu.stack.notmask;
				reg_esp.dword |= (reg_ebp.dword & CPU.cpu.stack.mask);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					reg_ebp.dword = CPU.CPU_Pop32();
				} else {
					reg_ebp.word(CPU.CPU_Pop16());
				}
				return HANDLED;
			}
		};

		/* RETF Iw */
		ops[0xca] = new OP() {
			final public int call() {
				/* Bitu */int words = Fetchw();
				Flags.FillFlags();
				CPU.CPU_RET((prefixes & Core.PREFIX_DW) != 0, words, GETIP());
				return CONTINUE;
			}
		};

		/* RETF */
		ops[0xcb] = new OP() {
			final public int call() {
				Flags.FillFlags();
				CPU.CPU_RET((prefixes & Core.PREFIX_DW) != 0, 0, GETIP());
				return CONTINUE;
			}
		};

		/* INT3 */
		ops[0xcc] = new OP() {
			final public int call() {
				CPU.CPU_SW_Interrupt_NoIOPLCheck(3, GETIP());
				if (CPU_TRAP_CHECK) CPU.cpu.trap_skip = true;
				return CONTINUE;
			}
		};

		/* INT Ib */
		ops[0xcd] = new OP() {
			final public int call() {
				/* Bit8u */int num = Fetchb();
				CPU.CPU_SW_Interrupt(num, GETIP());
				if (CPU_TRAP_CHECK) CPU.cpu.trap_skip = true;
				return CONTINUE;
			}
		};

		/* INTO */
		ops[0xce] = new OP() {
			final public int call() {
				if (Flags.get_OF()) {
					CPU.CPU_SW_Interrupt(4, GETIP());
					if (CPU_TRAP_CHECK) CPU.cpu.trap_skip = true;
					return CONTINUE;
				}
				return HANDLED;
			}
		};

		/* IRET */
		ops[0xcf] = new OP() {
			final public int call() {
				CPU.CPU_IRET((prefixes & Core.PREFIX_DW) != 0, GETIP());
				if (CPU_TRAP_CHECK) {
					if (GETFLAG(TF) != 0) {
						CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
						return CBRET_NONE;
					}
				}
				if (CPU_PIC_CHECK) if (GETFLAG(IF) != 0 && Pic.PIC_IRQCheck != 0) return CBRET_NONE;
				return CONTINUE;
			}
		};

		/* GRP2 Eb,1  */ ops[0xd0] = new SHIFTb(1);
		/* GRP2 Ew,1  */ ops[0xd1] = new SHIFTw(1);
		/* GRP2 Eb,CL */ ops[0xd2] = new SHIFTb(2);
		/* GRP2 Ew,CL */ ops[0xd3] = new SHIFTw(2);

		/* AAM Ib */
		ops[0xd4] = new OP() {
			final public int call() {
				if (!Instructions.AAM(Fetchb())) return RUNEXCEPTION();
				return HANDLED;
			}
		};

		/* AAD Ib */
		ops[0xd5] = new OP() {
			final public int call() {
				Instructions.AAD(Fetchb());
				return HANDLED;
			}
		};

		/* SALC */
		ops[0xd6] = new OP() {
			final public int call() {
				reg_eax.low(Flags.get_CF() ? 0xFF : 0);
				return HANDLED;
			}
		};

		/* XLAT */
		ops[0xd7] = new OP() {
			final public int call() {
				if ((prefixes & PREFIX_ADDR) != 0) {
					reg_eax.low(Memory.mem_readb(base_ds + (reg_ebx.dword + reg_eax.low())));
				} else {
					reg_eax.low(Memory.mem_readb(base_ds + ((reg_ebx.word() + reg_eax.low()) & 0xFFFF)));
				}
				return HANDLED;
			}
		};

		/* FPU ESC 0 */
		ops[0xd8] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC0_Normal(rm);
					} else {
						FPU.FPU_ESC0_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 1 */
		ops[0xd9] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC1_Normal(rm);
					} else {
						//TODO FNSTCW
						FPU.FPU_ESC1_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 2 */
		ops[0xda] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC2_Normal(rm);
					} else {
						FPU.FPU_ESC2_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 3 */
		ops[0xdb] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						//TODO FNINIT
						FPU.FPU_ESC3_Normal(rm);
					} else {
						FPU.FPU_ESC3_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 4 */
		ops[0xdc] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC4_Normal(rm);
					} else {
						FPU.FPU_ESC4_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 5 */
		ops[0xdd] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC5_Normal(rm);
					} else {
						//TODO FNSTSW
						FPU.FPU_ESC5_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 6 */
		ops[0xde] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						FPU.FPU_ESC6_Normal(rm);
					} else {
						FPU.FPU_ESC6_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		/* FPU ESC 7 */
		ops[0xdf] = new OP() {
			final public int call() {
				if (Config.C_FPU) {
					/*Bit8u*/int rm = Fetchb();
					if (rm >= 0xc0) {
						//TODO FNSTSW_AX
						FPU.FPU_ESC7_Normal(rm);
					} else {
						FPU.FPU_ESC7_EA(rm, getEaa(rm));
					}
				} else {
					/*Bit8u*/int rm = Fetchb();
					Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_NORMAL, "FPU used");
					if (rm < 0xc0) getEaa(rm);
					return NOT_HANDLED;
				}
				return HANDLED;
			}
		};

		//LOOP(boolean loop, boolean z, boolean nz) {
		/* LOOPNZ */ ops[0xe0] = new LOOP(true, false, true);
		/* LOOPZ  */ ops[0xe1] = new LOOP(true, true, false);
		/* LOOP   */ ops[0xe2] = new LOOP(true, false, false);
		/* JCXZ   */ ops[0xe3] = new LOOP(false, false, false);

		//IOOp(boolean input, boolean w, boolean dx)
		/* IN AL,Ib  */ ops[0xe4] = new IOOp(true, false, false);
		/* IN AX,Ib  */ ops[0xe5] = new IOOp(true, true, false);
		/* OUT Ib,AL */ ops[0xe6] = new IOOp(false, false, false);
		/* OUT Ib,AX */ ops[0xe7] = new IOOp(false, true, false);

		/* CALL Jw */
		ops[0xe8] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bit32s */int addip = Fetchds();
					CPU.CPU_Push32(GETIP());
					SAVEIP();
					reg_eip += addip;
				} else {
					/* Bit16u */int addip = Fetchws();
					CPU.CPU_Push16(GETIP() & 0xFFFF);
					SAVEIP();
					reg_eip = (reg_eip + addip) & 0xFFFF;
				}
				return CONTINUE;
			}
		};
		/* JMP Jw */
		ops[0xe9] = new OP() {
			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bit32s */int addip = Fetchds();
					SAVEIP();
					reg_eip += addip;
				} else {
					/* Bit16u */int addip = Fetchws();
					SAVEIP();
					reg_eip = (reg_eip + addip) & 0xFFFF;
				}
				return CONTINUE;
			}
		};

		/* JMP Ap */
		ops[0xea] = new OP() {
			int newcs;
			int newip;

			final public int call() {
				if ((prefixes & Core.PREFIX_DW) != 0) {
					/* Bit32u */ newip = Fetchd();
					/* Bit16u */ newcs = Fetchw();
					FillFlags();
					CPU.CPU_JMP(true, newcs, newip, GETIP());
				} else {
					/* Bit16u */ newip = Fetchw();
					/* Bit16u */ newcs = Fetchw();
					Flags.FillFlags();
					CPU.CPU_JMP(false, newcs, newip, GETIP());
				}
				if (CPU_TRAP_CHECK) {
					if (GETFLAG(TF) != 0) {
						CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
						return CBRET_NONE;
					}
				}
				return CONTINUE;
			}

			public String toString() {
				return "JMP " + ((prefixes & Core.PREFIX_DW) != 0 ? "D" : "W") + " " + Integer.toString(newcs, 16) + " " + Integer.toString(newip, 16);
			}
		};

		/* JMP Jb */
		ops[0xeb] = new OP() {
			final public int call() {
				/* Bit32s */int addip = Fetchbs();
				if ((prefixes & Core.PREFIX_DW) != 0) {
					SAVEIP();
					reg_eip += addip;
				} else {
					SAVEIP();
					reg_eip = (reg_eip + addip) & 0xFFFF;
				}
				return CONTINUE;
			}
		};

		//IOOp(boolean input, boolean w, boolean dx)
		/* IN AL,DX  */ ops[0xec] = new IOOp(true, false, true);
		/* IN AX,DX  */ ops[0xed] = new IOOp(true, true, true);
		/* OUT DX,AL */ ops[0xee] = new IOOp(false, false, true);
		/* OUT DX,AX */ ops[0xef] = new IOOp(false, true, true);

		//		/* LOCK */
		//		ops[0xf0] = new OP() {
		//			final public int call() {
		//				// if (Log.level<=LogSeverities.LOG_NORMAL)
		//				// Log.log(LogTypes.LOG_CPU,LogSeverities.LOG_NORMAL,"CPU:LOCK"); /* FIXME: see
		//				// case D_LOCK in core_full/new Instructions.load()h */
		//				System.out.println("LOCK");
		////				if (false) {
		////					prefixes |= PREFIX_LOCK;
		////					return RESTART;
		////				} else {
		//					return HANDLED;
		////				}
		//			}
		//		};

		/* ICEBP */
		ops[0xf1] = new OP() {
			final public int call() {
				CPU.CPU_SW_Interrupt_NoIOPLCheck(1, GETIP());
				if (CPU_TRAP_CHECK) CPU.cpu.trap_skip = true;
				return CONTINUE;
			}
		};

		/* HLT */
		ops[0xf4] = new OP() {
			final public int call() {
				if (CPU.cpu.pmode && CPU.cpu.cpl != 0) return EXCEPTION(CPU.EXCEPTION_GP);
				Flags.FillFlags();
				CPU.CPU_HLT(GETIP());
				return CBRET_NONE;
			}
		};

		/* CMC */
		ops[0xf5] = new OP() {
			final public int call() {
				Flags.FillFlags();
				SETFLAGBIT(CF, (CPU_Regs.flags & CPU_Regs.CF) == 0);
				return HANDLED;
			}
		};

		/* GRP3 Eb(,Ib) */
		ops[0xf6] = new OP() {
			final public int call() {
				Targets t = getTargets(false);
				switch (t.which) {
				case 0x00: /* TEST Ew,Iw */
				case 0x01: /* TEST Ew,Iw Undocumented*/
				{
					int op = Fetchb();
					TESTB(op, t.e.read());
					break;
				}
				case 0x02: /* NOT Ew */
				{
					t.e.write(~t.e.read());
					break;
				}
				case 0x03: /* NEG Ew */
				{
					t.e.write(Instructions.Negb(t.e.read()));
					break;
				}
				case 0x04: /* MUL AX,Ew */
					MULB(t.e.read());
					break;
				case 0x05: /* IMUL AX,Ew */
					IMULB(t.e.read());
					break;
				case 0x06: /* DIV Ew */
					if (!DIVB(t.e.read())) return RUNEXCEPTION();
					break;
				case 0x07: /* IDIV Ew */
					if (!IDIVB(t.e.read())) return RUNEXCEPTION();
					break;
				}
				return HANDLED;
			}
		};

		/* GRP3 Ew(,Iw) */
		ops[0xf7] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					switch (t.which) {
					case 0x00: /* TEST Ew,Iw */
					case 0x01: /* TEST Ew,Iw Undocumented*/
					{
						int op = Fetchd();
						TESTD(op, t.e.read());
						break;
					}
					case 0x02: /* NOT Ew */
					{
						t.e.write(~t.e.read());
						break;
					}
					case 0x03: /* NEG Ew */
					{
						t.e.write(Instructions.Negd(t.e.read()));
						break;
					}
					case 0x04: /* MUL AX,Ew */
						MULD(t.e.read());
						break;
					case 0x05: /* IMUL AX,Ew */
						IMULD(t.e.read());
						break;
					case 0x06: /* DIV Ew */
						if (!DIVD(t.e.read())) return RUNEXCEPTION();
						break;
					case 0x07: /* IDIV Ew */
						if (!IDIVD(t.e.read())) return RUNEXCEPTION();
						break;
					}
				} else {
					switch (t.which) {
					case 0x00: /* TEST Ew,Iw */
					case 0x01: /* TEST Ew,Iw Undocumented*/
					{
						int op = Fetchw();
						TESTW(op, t.e.read());
						break;
					}
					case 0x02: /* NOT Ew */
					{
						t.e.write(~t.e.read());
						break;
					}
					case 0x03: /* NEG Ew */
					{
						t.e.write(Instructions.Negw(t.e.read()));
						break;
					}
					case 0x04: /* MUL AX,Ew */
						MULW(t.e.read());
						break;
					case 0x05: /* IMUL AX,Ew */
						IMULW(t.e.read());
						break;
					case 0x06: /* DIV Ew */
						if (!DIVW(t.e.read())) return RUNEXCEPTION();
						break;
					case 0x07: /* IDIV Ew */
						if (!IDIVW(t.e.read())) return RUNEXCEPTION();
						break;
					}
				}
				return HANDLED;
			}
		};

		/* CLC */
		ops[0xf8] = new OP() {
			final public int call() {
				Flags.FillFlags();
				SETFLAGBIT(CF, false);
				return HANDLED;
			}
		};

		/* STC */
		ops[0xf9] = new OP() {
			final public int call() {
				Flags.FillFlags();
				SETFLAGBIT(CF, true);
				return HANDLED;
			}
		};

		/* CLI */
		ops[0xfa] = new OP() {
			final public int call() {
				if (CPU.CPU_CLI()) return RUNEXCEPTION();
				return HANDLED;
			}

			public String toString() {
				return "CLI";
			}
		};

		/* STI */
		ops[0xfb] = new OP() {
			final public int call() {
				if (CPU.CPU_STI()) return RUNEXCEPTION();
				if (CPU_PIC_CHECK) if (GETFLAG(IF) != 0 && Pic.PIC_IRQCheck != 0) return DECODE_END;
				return HANDLED;
			}

			public String toString() {
				return "STI";
			}
		};

		/* CLD */
		ops[0xfc] = new OP() {
			final public int call() {
				SETFLAGBIT(DF, false);
				return HANDLED;
			}

			public String toString() {
				return "CLD";
			}
		};

		/* STD */
		ops[0xfd] = new OP() {
			final public int call() {
				SETFLAGBIT(DF, true);
				return HANDLED;
			}
		};

		/* GRP4 Eb */
		ops[0xfe] = new OP() {
			final public int call() {
				Targets t = getTargets(false);
				switch (t.which) {
				case 0x00: /* INC Eb */
					t.e.write(INCB(t.e.read()));
					break;
				case 0x01: /* DEC Eb */
					t.e.write(DECB(t.e.read()));
					break;
				case 0x07: /* CallBack dosbox special instruction */
				{
					CPU.returnValue = Fetchw();
					Flags.FillFlags();
					SAVEIP();
					return RETURN;
				}
				default:
					//Log.exit("Illegal GRP4 Call "+((rm>>3) & 7));
					break;
				}
				return HANDLED;
			}
		};

		/* GRP5 Ew */
		ops[0xff] = new OP() {
			final public int call() {
				Targets t = getTargets(true);
				if ((prefixes & Core.PREFIX_DW) != 0) {
					switch (t.which) {
					case 0x00: /* INC Ed */
						t.e.write(INCD(t.e.read()));
						break;
					case 0x01: /* DEC Ed */
						t.e.write(DECD(t.e.read()));
						break;
					case 0x02: /* CALL NEAR Ed */
					{
						int eip = t.e.read();
						CPU.CPU_Push32(GETIP());
						reg_eip = eip;
						return CONTINUE;
					}
					case 0x03: /* CALL FAR Ed */
					{
						/*PhysPt*/int eaa = t.ea;
						/*Bit32u*/int newip = Memory.mem_readd(eaa);
						/*Bit16u*/int newcs = Memory.mem_readw(eaa + 4);
						FillFlags();
						CPU.CPU_CALL(true, newcs, newip, GETIP());
						if (CPU_TRAP_CHECK) if (GETFLAG(TF) != 0) {
							CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
							return CBRET_NONE;
						}
						return CONTINUE;
					}
					case 0x04: /* JMP NEAR Ed */
						reg_eip = t.e.read();
						return CONTINUE;
					case 0x05: /* JMP FAR Ed */
					{
						/*PhysPt*/int eaa = t.ea;
						/*Bit32u*/int newip = Memory.mem_readd(eaa);
						/*Bit16u*/int newcs = Memory.mem_readw(eaa + 4);
						FillFlags();
						CPU.CPU_JMP(true, newcs, newip, GETIP());
						if (CPU_TRAP_CHECK) if (GETFLAG(TF) != 0) {
							CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
							return CBRET_NONE;
						}
						return CONTINUE;
					}
					case 0x06: /* Push Ed */
						CPU.CPU_Push32(t.e.read());
						break;
					default:
						if (Log.level <= LogSeverities.LOG_ERROR) Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_ERROR, "CPU:66:GRP5:Illegal call " + Integer.toString(t.which, 16));
						return ILLEGAL_OPCODE;
					}
				} else {
					switch (t.which) {
					case 0x00: /* INC Ew */
						t.e.write(INCW(t.e.read()));
						break;
					case 0x01: /* DEC Ew */
						t.e.write(DECW(t.e.read()));
						break;
					case 0x02: /* CALL Ev */
					{
						int eip = t.e.read();
						CPU.CPU_Push16(GETIP() & 0xFFFF);
						reg_eip = eip;
						return CONTINUE;
					}
					case 0x03: /* CALL Ep */
					{
						/*PhysPt*/int eaa = t.ea;
						/*Bit16u*/int newip = Memory.mem_readw(eaa);
						/*Bit16u*/int newcs = Memory.mem_readw(eaa + 2);
						Flags.FillFlags();
						CPU.CPU_CALL(false, newcs, newip, GETIP());
						if (CPU_TRAP_CHECK) {
							if (GETFLAG(TF) != 0) {
								CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
								return CBRET_NONE;
							}
						}
						return CONTINUE;
					}
					case 0x04: /* JMP Ev */
						reg_eip = t.e.read();
						return CONTINUE;
					case 0x05: /* JMP Ep */
					{
						/*PhysPt*/int eaa = t.ea;
						/*Bit16u*/int newip = Memory.mem_readw(eaa);
						/*Bit16u*/int newcs = Memory.mem_readw(eaa + 2);
						Flags.FillFlags();
						CPU.CPU_JMP(false, newcs, newip, GETIP());
						if (CPU_TRAP_CHECK) {
							if (GETFLAG(TF) != 0) {
								CPU.cpudecoder = Core_full.CPU_Core_Normal_Trap_Run;
								return CBRET_NONE;
							}
						}
						return CONTINUE;
					}
					case 0x06: /* PUSH Ev */
						CPU.CPU_Push16(t.e.read());
						break;
					default:
						if (Log.level <= LogSeverities.LOG_ERROR) Log.log(LogTypes.LOG_CPU, LogSeverities.LOG_ERROR, "CPU:GRP5:Illegal Call " + Integer.toString(t.which, 16));
						return ILLEGAL_OPCODE;
					}
				}
				return HANDLED;
			}
		};

	}
}
